home *** CD-ROM | disk | FTP | other *** search
- ;*****************************************************************************
- ;* *
- ;* HIMEM.ASM - Chip Anderson *
- ;* *
- ;* Extended Memory Specification Driver - *
- ;* Copyright 1988, Microsoft Corporation *
- ;* *
- ;* The HMA was originally envisioned by Ralph Lipe. *
- ;* Original XMS spec designed by Aaron Reynolds, Chip Anderson, and *
- ;* Tony Gosling. Additional spec suggestions by Phil Barrett and David *
- ;* Weise of Microsoft, Ed McNierney of Lotus and Bob Smith of Qualitas. *
- ;* *
- ;* MoveExtMemory function written by Tony Gosling. *
- ;* *
- ;* AT&T 6300 support added by Bill Hall, Olivetti ATC, Cupertino, CA *
- ;* HP Vectra support added by Ralph Peterson, Hewlett Packard Corp. *
- ;* *
- ;*****************************************************************************
-
- XMSVersion equ 0200h
- HimemVersion equ 0206h
-
- ; Version -
- ;
- ; 1.00 - Written 4/17/88
- ; 1.01 - Added Global/Temporary Enable of A20 4/18/88
- ; 1.02 - Don't use DOS to change interrupts 4/19/88
- ; - Return 1 for success in Disable cases 4/19/88
- ; - Prevent disables if A20 enabled at start 4/19/88
- ; - Added INT 2F handler check 4/19/88
- ; - Used smarter hooking routine 4/19/88
- ; 1.03 - Optimized some code 4/20/88
- ; - Temporarily Disable properly 4/20/88
- ; - Disable INT's while changing vars 4/20/88
- ; 1.04 - Check to see if A20 works during init 4/23/88
- ; - Fixed PS/2 support 4/23/88
- ; 1.05 - Added QueryExtMemory and AllocExtMemory 4/25/88
- ; 1.06 - Never remove the INT 15h hook once it is in 4/27/88
- ; - Changed ExtMemory calls to provide "full" MM 4/27/88
- ; - Force A20 line off on PS2's at init time 4/27/88
- ; 1.07 - Added Multiple A20 Handler support 5/01/88
- ; - Added popff macro 5/01/88
- ; - REP MOVSW words not bytes 5/04/88
- ; 1.08 - Made popff relocateable 5/04/88
- ; - Added support for the AT&T 6300 Plus 5/05/88
- ; - Added support for the HP Vectra 5/06/88
- ; 1.09 - Added CEMM recognition code 5/16/88
- ; - Don't automatically trash BX in HMMControl 5/17/88
- ; 1.10 - Change PS/2 ID routine to use Watchdog timer 6/02/88
- ; - Changed CEMM recognition string to just VDISK 6/07/88
- ; - Fixed 2 instance bug 6/14/88
- ; 1.11 - Changed INT 2F multiplex number to 43h 6/23/88
- ; - Fixed HP Vectra support for older Vectras 6/23/88
- ; - Fixed Block Move register trashing bug 6/25/88
- ; 2.00 - Updated to XMS v2.00 7/10/88
- ; - Reworked initialization code 7/12/88
- ; - Reworked reentrancy issues 7/13/88
- ; - Finialized A20 handling 7/14/88
- ; - Added parameter support 7/14/88
- ; 2.01 - Official version with Vecta and 6300 support 7/15/88
- ; 2.02 - Removed INT 1 from MoveExtMemory 7/19/88
- ; - Fixed minor problems in QueryExtMemory 7/19/88
- ; 2.03 - Added 386 Big Mode MoveBlock 8/04/88
- ; - Added Compaq "Built-In" Memory support 8/05/88
- ; - Fixed 64K-free Installation bug 8/05/88
- ; - Change PS/2 detection code yet again 8/08/88
- ; 2.04 - Fixed "A20 On" Message bug (ugh) 8/09/88
- ; - Fixed A20 Init testing code 8/09/88
- ; - Cleaned up for publication 8/09/88
- ; 2.05 - Bug Fix: Subtract 64K from first EMB for HMA 11/30/88
- ; - Bug Fix: Check for NUMHANDLES=0 case 12/14/88
- ; 2.06 - Source code update 2/07/89
- ; Bug Fix: Restore 286 initialization code 3/21/89
-
- name Himem
- title 'HIMEM.SYS - Microsoft XMS Device Driver'
-
- ;*--------------------------------------------------------------------------*
- ;* EQUATES *
- ;*--------------------------------------------------------------------------*
-
- DEFHANDLES equ 32 ; Default # of EMB handles
- MAXHANDLES equ 128 ; Max # of EMB handles
-
- cXMSFunctions equ 12h ; = # of last function+1!
-
- FREEFLAG equ 00000001b ; EMB Flags
- USEDFLAG equ 00000010b
- UNUSEDFLAG equ 00000100b
-
- ; XMS Error Codes.
- ERR_NOTIMPLEMENTED equ 080h
- ERR_VDISKFOUND equ 081h
- ERR_A20 equ 082h
- ERR_GENERAL equ 08Eh
- ERR_UNRECOVERABLE equ 08Fh
-
- ERR_HMANOTEXIST equ 090h
- ERR_HMAINUSE equ 091h
- ERR_HMAMINSIZE equ 092h
- ERR_HMANOTALLOCED equ 093h
-
- ERR_OUTOMEMORY equ 0A0h
- ERR_OUTOHANDLES equ 0A1h
- ERR_INVALIDHANDLE equ 0A2h
- ERR_SHINVALID equ 0A3h
- ERR_SOINVALID equ 0A4h
- ERR_DHINVALID equ 0A5h
- ERR_DOINVALID equ 0A6h
- ERR_LENINVALID equ 0A7h
- ERR_OVERLAP equ 0A8h
- ERR_PARITY equ 0A9h
- ERR_EMBUNLOCKED equ 0AAh
- ERR_EMBLOCKED equ 0ABh
- ERR_LOCKOVERFLOW equ 0ACh
- ERR_LOCKFAIL equ 0ADh
-
- ERR_UMBSIZETOOBIG equ 0B0h
- ERR_NOUMBS equ 0B1h
- ERR_INVALIDUMB equ 0B2h
-
- .386p
-
- ; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is
- ; necessary to use the special OS-MERGE hardware to activate lines
- ; A20 to A23. However, these lines can be disabled only by resetting
- ; the processor. The address to which to return after reset are placed
- ; at 40:A2, noted here as RealLoc1.
-
- BiosSeg SEGMENT USE16 AT 40h ; Used to locate 6300 PLUS reset address
-
- org 00A2h
- RealLoc1 dd 0
-
- BiosSeg ends
-
-
- ; Macro to avoid the 286 POPF bug. Performs a harmless IRET to simulate a
- ; popf. Some 286s allow interrupts to sneak in during a real popf.
-
- popff macro
- push cs
- call pPPFIRet ; Defined as the offset of any IRET
- endm
-
- ;*--------------------------------------------------------------------------*
- ;* SEGMENT DEFINITION *
- ;*--------------------------------------------------------------------------*
-
- CODE SEGMENT PARA PUBLIC USE16 'CODE'
-
- assume cs:code,ds:code,es:code
-
- org 0
-
- ; The Driver Header definition.
- Header dd -1 ; Link to next driver, -1 = end of list
- dw 1010000000000000b
- ; Device attributes, Non-IBM bit set
- dw Strategy ; "Stategy" entry point
- dw Interrupt ; "Interrupt" entry point
- db 'XMSXXXX0' ; Device name
-
-
- ;****************************************************************************
- ;* *
- ;* Data Structures and Global Variables - *
- ;* *
- ;****************************************************************************
-
- ; The driver Request Header structure definition.
- ReqHdr struc
- ReqLen db ?
- Unit db ?
- Command db ?
- Status dw ?
- Reserved db 8 dup (?)
- Units db ?
- Address dd ?
- pCmdLine dd ?
- ReqHdr ends
-
- ; An EMB Handle structure definition.
- Handle struc ; Handle Table Entry
- Flags db ? ; Unused/InUse/Free
- cLock db ? ; Lock count
- Base dw ? ; 32-bit base address in K
- Len dw ? ; 32-bit length in K
- Handle ends
-
- ; Extended Memory Move Block structure definition.
- MoveExtendedStruc struc
- bCount dd ? ; Length of block to move
- SourceHandle dw ? ; Handle for souce
- SourceOffset dd ? ; Offset into source
- DestHandle dw ? ; Handle for destination
- DestOffset dd ? ; Offset into destination
- MoveExtendedStruc ends
-
- ; The Global variables.
- pPPFIRet dw PPFIRet ; The offset of an IRET for the POPFF macro
- pReqHdr dd ? ; Pointer to MSDOS Request Header structure
- pInt15Vector dw 15h*4,0 ; Pointer to the INT 15 Vector
- PrevInt15 dd 0 ; Original INT 15 Vector
- PrevInt2F dd 0 ; Original INT 2F Vector
- fHMAInUse db 0 ; High Memory Control Flag, != 0 -> In Use
- fCanChangeA20 db 0 ; A20 Enabled at start?
- fHMAMayExist db 0 ; True if the HMA could exist at init time
- fHMAExists db 0 ; True if the HMA exists
- fVDISK db 0 ; True if a VDISK device was found
- EnableCount dw 0 ; A20 Enable/Disable counter
- fGlobalEnable dw 0 ; Global A20 Enable/Disable flag
- KiddValley dw 0 ; The address of the handle table
- KiddValleyTop dw 0 ; Points to the end of the handle table
- MinHMASize dw 0 ; /HMAMIN= parameter value
- cHandles dw DEFHANDLES ; # of handles to allocate
-
- cImplementedFuncs db cXMSFunctions-3 ; Omit the UMB functions
- ; and ReallocEMB
-
- A20Handler dw 0 ; Offset of the A20 Handler
-
- BIMBase dw 0 ; Base address and Lenght of remaining Compaq
- BIMLength dw 0 ; Built-In Memory (set at Init time)
-
- MemCorr dw 0 ; KB of memory at FA0000 on AT&T 6300 Plus.
- ; This is used to correct INT 15h,
- ; Function 88h return value.
- OldStackSeg dw 0 ; Stack segment save area for 6300 Plus.
- ; Needed during processor reset.
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Strategy - *
- ;* *
- ;* Called by MS-DOS when ever the driver is accessed. *
- ;* *
- ;* ARGS: ES:BX = Address of Request Header *
- ;* RETS: Nothing *
- ;* REGS: Preserved *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- Strategy proc far
-
- ; Save the address of the request header.
- mov word ptr cs:[pReqHdr],bx
- mov word ptr cs:[pReqHdr][2],es
- ret
-
- Strategy endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Interrupt - *
- ;* *
- ;* Called by MS-DOS immediately after Strategy routine *
- ;* *
- ;* ARGS: None *
- ;* RETS: Return code in Request Header's Status field *
- ;* REGS: Preserved *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- Interrupt proc far
-
- ; Save the registers including flags.
- push ax ; We cannot use pusha\popa because
- push bx ; we could be on an 8086 at this point
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
- pushf
-
- ; Set DS=CS for access to global variables.
- push cs
- pop ds
-
- les di,[pReqHdr] ; ES:DI = Request Header
-
- mov bl,es:[di.Command] ; Get Function code in BL
-
- or bl,bl ; Only Function 00h (Init) is legal
- jz short IInit
-
- cmp bl,16 ; Test for "legal" DOS functions
- jle short IOtherFunc
-
- IBogusFunc: mov ax,8003h ; Return "Unknown Command"
- jmp short IExit
-
- IOtherFunc: xor ax,ax ; Return zero for unsupported functions
- jmp short IExit
-
- ; Initialize the driver.
- IInit: call InitDriver
-
- les di,[pReqHdr] ; Restore ES:DI = Request Header
-
- IExit: or ax,0100h ; Turn on the "Done" bit
- mov es:[di.Status],ax ; Store return code
-
- ; Restore the registers.
- popff
- pop bp
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
-
- Interrupt endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Int2FHandler - *
- ;* *
- ;* Hooks Function 43h, Subfunction 10h to return the *
- ;* address of the High Memory Manager Control function. *
- ;* Also returns 80h if Function 43h, Subfunction 0h is requested. *
- ;* *
- ;* ARGS: AH = Function, AL = Subfunction *
- ;* RETS: ES:BX = Address of XMMControl function (if AX=4310h) *
- ;* AL = 80h (if AX=4300) *
- ;* REGS: Preserved except for ES:BX (if AX=4310h) *
- ;* Preserved except for AL (if AX=4300h) *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- Int2FHandler proc far
-
- sti ; Flush any queued interrupts
-
- cmp ah,43h ; Function 43h?
- jne short I2FNextInt
- or al,al ; Subfunction 0?
- jne short I2FNextSub ; No, continue
-
- ; Indicate that an XMS driver is installed.
- mov al,80h ; Return 80h in AL
- PPFIRet: iret ; Label sets up the POPFF macro
-
- I2FNextSub: cmp al,10h ; Subfunction 10?
- jne short I2FNextInt ; No, goto next handler
-
- ; Return the address of the XMS Control function in ES:BX.
- push cs
- pop es
- mov bx,offset XMMControl
- iret
-
- ; Continue down the Int 2F chain.
- I2FNextInt: cli ; Disable interrupts again
- jmp cs:[PrevInt2F]
-
- Int2FHandler endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* ControlJumpTable - *
- ;* *
- ;* Contains the address for each of the XMS Functions. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ControlJumpTable label word
- dw Version ; Function 00h
- dw RequestHMA ; Function 01h
- dw ReleaseHMA ; Function 02h
- dw GlobalEnableA20 ; Function 03h
- dw GlobalDisableA20 ; Function 04h
- dw LocalEnableA20 ; Function 05h
- dw LocalDisableA20 ; Function 06h
- dw IsA20On ; Function 07h
- dw QueryExtMemory ; Function 08h
- dw AllocExtMemory ; Function 09h
- dw FreeExtMemory ; Function 0Ah
- dw MoveBlock ; Function 0Bh
- dw LockExtMemory ; Function 0Ch
- dw UnlockExtMemory ; Function 0Dh
- dw GetExtMemoryInfo ; Function 0Eh
-
- ; We don't implement Realloc in this version.
- ; dw ReallocExtMemory ; Function 0Fh
-
- ; We don't implement the UMB functions.
- ; dw RequestUMB ; Function 14
- ; dw ReleaseUMB ; Function 15
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* XMMControl - *
- ;* *
- ;* Main Entry point for the Extended Memory Manager *
- ;* *
- ;* ARGS: AH = Function, AL = Optional parm *
- ;* RETS: AX = Function Success Code, BL = Optional Error Code *
- ;* REGS: AX, BX, DX and ES may not be preserved depending on function *
- ;* *
- ;* INTERNALLY REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- XMMControl proc far
-
- jmp short XCControlEntry ; For "hookability"
- nop ; NOTE: The jump must be a
- nop ; short jump to indicate
- nop ; the end of any hook chain.
- ; The nop's allow a far jump
- ; to be patched in.
- XCControlEntry:
- ; Preserve the following registers.
- push cx
- push si
- push di
- push ds
- push es
- pushf
-
- ; Save DS in ES.
- push ds
- pop es ; NOTE: ES cannot be used for parms!
-
- ; Set DS equal to CS.
- push cs
- pop ds
-
- ; Preserve the current function number.
- push ax
-
- ; Is this a call to "Get XMS Version"?
- or ah,ah
- jz short XCCallFunc ; Yes, don't hook INT 15h yet
-
- ; Is this a valid function number?
- cmp ah,[cImplementedFuncs]
- jb short XCCheckHook
- pop ax ; No, Un-preserve AX and return an error
- xor ax,ax
- mov bl,ERR_NOTIMPLEMENTED
- jmp short XCExit
-
- ; Is INT 15h already hooked?
- XCCheckHook:pushf
- cli ; This is a critical section
-
- cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
- jne short XCCheckVD
-
- ; Try to claim all remaining extended memory.
- call HookInt15
-
- ; Was a VDISK device found?
- XCCheckVD: popff ; End of critical section
- cmp [fVDISK],0
- je short XCCallFunc
- pop ax ; Yes, Un-preserve AX and return an error
- xor ax,ax
- mov bl,ERR_VDISKFOUND
- xor dx,dx
- jmp short XCExit
-
- ; Call the appropriate API function.
- XCCallFunc: pop ax ; Restore AX
- mov al,ah
- xor ah,ah
- shl ax,1
- mov di,ax ; NOTE: DI cannot be used for parms!
-
- call word ptr [ControlJumpTable+di]
-
- ; Restore the preserved registers.
- XCExit: popff ; NOTE: Flags must be restored immediately
- pop es ; after the call to the API functions.
- pop ds
- pop di
- pop si
- pop cx
- ret
-
- XMMControl endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Get XMS Version Number - FUNCTION 00h *
- ;* *
- ;* Returns the XMS version number *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = XMS Version Number *
- ;* BX = Internal Driver Version Number *
- ;* DX = 1 if HMA exists, 0 if it doesn't *
- ;* REGS: AX, BX and DX are clobbered *
- ;* *
- ;* INTERNALLY REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- Version proc near
-
- mov ax,XMSVersion
- mov bx,HimemVersion
- xor dh,dh
-
- ; Is Int 15h hooked?
- cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
- jne short VHooked
- mov dl,[fHMAMayExist] ; No, return the status at
- ret ; init time.
-
- VHooked: mov dl,[fHMAExists] ; Yes, return the real status
- ret
-
- Version endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* HookInt15 - *
- ;* *
- ;* Insert the INT 15 hook *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, BX, CS, DI, SI, and Flags are clobbered *
- ;* *
- ;* EXTERNALLY NON-REENTRANT *
- ;* Interrupts must be disabled before calling this function. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- HookInt15 proc near
-
- push es
-
- ; Has a VDISK device been installed?
- call IsVDISKIn
- cmp [fVDISK],0
- je short HINoVD ; No, continue
- pop es ; Yes, return without hooking
- ret
-
- HINoVD: mov ah,88h ; Is 64K of Extended memory around?
- int 15h
- sub ax,[MemCorr] ; 6300 Plus may have memory at FA0000h
- cmp ax,64
- jb short HIInitMemory ; Less than 64K free? Then no HMA.
- mov [fHMAExists],1
-
- HIInitMemory:
- ; Init the first handle to be one huge free block.
- mov bx,[KiddValley]
- mov [bx.Flags],FREEFLAG
- mov [bx.Len],ax
- mov [bx.Base],1024
-
- ; Reserve room for the HMA if it exists. 11-30-88 ChipA
- cmp [fHMAExists],0
- je short HICont
- add [bx.Base],64
- sub [bx.Len],64
-
- ; See if any Compaq "Built In Memory" exists.
- HICont: mov ax,[BIMBase]
- or ax,ax
- jz short HIHookEmHorns
-
- mov cx,[BIMLength]
-
- ; Fill out the next handle entry.
- add bx,size Handle
- mov [bx.Flags],FREEFLAG
- mov [bx.Len],cx
- mov [bx.Base],ax
-
- ; Save the current INT 15 vector.
- HIHookEmHorns:
- les si,dword ptr pInt15Vector
-
- ; Exchange the old vector with the new one.
- mov ax,offset Int15Handler
- xchg ax,es:[si][0]
- mov word ptr [PrevInt15][0],ax
- mov ax,cs
- xchg ax,es:[si][2]
- mov word ptr [PrevInt15][2],ax
-
- pop es
- ret
-
- HookInt15 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* IsVDISKIn - *
- ;* *
- ;* Looks for drivers which use the IBM VDISK method of allocating *
- ;* Extended Memory. XMS is incompatible with the VDISK method. *
- ;* *
- ;* ARGS: None *
- ;* RETS: None. Sets "fVDISK" accordingly *
- ;* REGS: AX, CX, SI, DI and Flags are clobbered *
- ;* *
- ;* INTERNALLY REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- pVDISK label dword
- dw 00013h
- dw 0FFFFh
-
- szVDISK db 'VDISK'
-
- IsVDISKIn proc near
-
- ; Look for "VDISK" starting at the 4th byte of extended memory.
- call LocalEnableA20 ; Turn on A20
-
- push ds
- push es
-
- ; Set up the comparison.
- lds si,cs:pVDISK
- push cs
- pop es
- mov di,offset szVDISK
- mov cx,5
- cld
- rep cmpsb ; Do the comparison
-
- pop es ; Restore ES and DS
- pop ds
-
- jz short IVIFoundIt
- mov [fVDISK],0 ; No VDISK device found
- jmp short IVIExit
-
- ; "VDISK" was found.
- IVIFoundIt: mov [fVDISK],1
-
- IVIExit: call LocalDisableA20
- ret ; Turn off A20
-
- IsVDISKIn endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Int15Handler - *
- ;* *
- ;* Hooks Function 88h to return zero as the amount of extended *
- ;* memory available in the system. *
- ;* *
- ;* Hooks Function 87h and preserves the state of A20 across the *
- ;* block move. *
- ;* *
- ;* ARGS: AH = Function, AL = Subfunction *
- ;* RETS: AX = 0 (if AH == 88h) *
- ;* REGS: AX is clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- I15RegSave dw ?
-
- Int15Handler proc far
-
- ; Is this a request for the amount of free extended memory?
- cmp ah,88h
- jne short I15HCont ; No, continue
-
- xor ax,ax ; Yes, return zero
- iret
-
- ; Is it a Block Move?
- I15HCont: cmp ah,87h
- jne short I15HNext ; No, continue
-
- ; Int 15h Block Move:
- cli ; Make sure interrupts are off
-
- ; Store the A20 line's state.
- pusha ; Preserve the registers
- call IsA20On
- mov cs:[I15RegSave],ax
- popa ; Restore the registers
-
- ; Call the previous Int 15h handler.
- pushf ; Simualate an interrupt
- call cs:[PrevInt15]
- pusha ; Preserve previous handler's return
-
- ; Was A20 on before?
- cmp cs:[I15RegSave],0
- je short I15HExit ; No, continue
- mov ax,1
- call cs:[A20Handler] ; Yes, turn A20 back on
-
- I15HExit: popa ; Restore the previous handler's return
- iret
-
- ; Continue down the Int 15h chain.
- I15HNext: jmp cs:[PrevInt15]
-
- Int15Handler endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* RequestHMA - FUNCTION 01h *
- ;* *
- ;* Give caller control of the High Memory Area if it is available. *
- ;* *
- ;* ARGS: DX = HMA space requested in bytes *
- ;* RETS: AX = 1 if the HMA was reserved, 0 otherwise. BL = Error Code *
- ;* REGS: AX, BX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- RequestHMA proc near
-
- cli ; This is a non-reentrant function.
- ; Flags are restored after the return.
- mov bl,ERR_HMAINUSE
- cmp [fHMAInUse],1 ; Is the HMA already allocated?
- je short RHRetErr
-
- mov bl,ERR_HMANOTEXIST
- cmp [fHMAExists],0 ; Is the HMA available?
- je short RHRetErr
-
- mov bl,ERR_HMAMINSIZE
- cmp dx,[MinHMASize] ; Is this guy allowed in?
- jb short RHRetErr
-
- mov ax,1
- mov [fHMAInUse],al ; Reserve the High Memory Area
- xor bl,bl ; Clear the error code
- ret
-
- RHRetErr: xor ax,ax ; Return failure with error code in BL
- ret
-
- RequestHMA endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* ReleaseHMA - FUNCTION 02h *
- ;* *
- ;* Caller is releasing control of the High Memory area *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if control is released, 0 otherwise. BL = Error Code *
- ;* REGS: AX, BX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ReleaseHMA proc near
-
- cli ; This is a non-reentrant function
-
- ; Is the HMA currently in use?
- mov al,[fHMAInUse]
- or al,al
- jz short RLHRetErr ; No, return error
-
- ; Release the HMA and return success.
- mov [fHMAInUse],0
- mov ax,1
- xor bl,bl
- ret
-
- RLHRetErr: xor ax,ax
- mov bl,ERR_HMANOTALLOCED
- ret
-
- ReleaseHMA endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GlobalEnableA20 - FUNCTION 03h *
- ;* *
- ;* Globally enable the A20 line *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
- ;* REGS: AX, BX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- GlobalEnableA20 proc near
-
- cli ; This is a non-reentrant function
-
- ; Is A20 already globally enabled?
- cmp [fGlobalEnable],1
- je short GEARet
-
- ; Attempt to enable the A20 line.
- call LocalEnableA20
- or ax,ax
- jz short GEAA20Err
-
- ; Mark A20 as globally enabled.
- mov [fGlobalEnable],1
-
- ; Return success.
- GEARet: mov ax,1
- xor bl,bl
- ret
-
- ; Some A20 error occured.
- GEAA20Err: mov bl,ERR_A20
- xor ax,ax
- ret
-
- GlobalEnableA20 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GlobalDisableA20 - FUNCTION 04h *
- ;* *
- ;* Globally disable the A20 line *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if the A20 line is disabled, 0 otherwise. BL = Error *
- ;* REGS: AX, BX and Flags are clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- GlobalDisableA20 proc near
-
- cli ; This is a non-reentrant function
-
- ; Is A20 already globally disabled?
- cmp [fGlobalEnable],0
- je short GDARet
-
- ; Attempt to disable the A20 line.
- call LocalDisableA20
- or ax,ax
- jz short GDAA20Err
-
- ; Mark A20 as globally disabled.
- mov [fGlobalEnable],0
-
- ; Return success.
- GDARet: mov ax,1
- xor bl,bl
- ret
-
- ; Some A20 error occured.
- GDAA20Err: mov bl,ERR_A20
- xor ax,ax
- ret
-
- GlobalDisableA20 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* LocalEnableA20 - FUNCTION 05h *
- ;* *
- ;* Locally enable the A20 line *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
- ;* REGS: AX, BX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- LocalEnableA20 proc near
-
- cli ; This is a non-reentrant function
-
- cmp [fCanChangeA20],1 ; Can we change A20?
- jne short LEARet ; No, don't touch A20
-
- ; Only actually enable A20 if the count is zero.
- cmp [EnableCount],0
- jne short LEAIncIt
-
- ; Attempt to enable the A20 line.
- mov ax,1
- call [A20Handler] ; Call machine-specific A20 handler
- or ax,ax
- jz short LEAA20Err
-
- LEAIncIt: inc [EnableCount]
-
- ; Return success.
- LEARet: mov ax,1
- xor bl,bl
- ret
-
- ; Some A20 error occurred.
- LEAA20Err: mov bl,ERR_A20
- xor ax,ax
- ret
-
- LocalEnableA20 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* LocalDisableA20 - FUNCTION 06h *
- ;* *
- ;* Locally disable the A20 line *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if the A20 line is disabled, 0 otherwise. BL = Error *
- ;* REGS: AX, BX and Flags are clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- LocalDisableA20 proc near
-
- cli ; This is a non-reentrant function
-
- cmp [fCanChangeA20],0 ; Can we change A20?
- je short LDARet ; No, don't touch A20
-
- ; Make sure the count's not zero.
- cmp [EnableCount],0
- je short LDAA20Err
-
- ; Only actually disable if the count is one.
- cmp [EnableCount],1
- jne short LDADecIt
-
- xor ax,ax
- call [A20Handler] ; Call machine-specific A20 handler
- or ax,ax
- jz short LDAA20Err
-
- LDADecIt: dec [EnableCount]
-
- ; Return success.
- LDARet: mov ax,1
- xor bl,bl
- ret
-
- ; Some A20 error occurred.
- LDAA20Err: mov bl,ERR_A20
- xor ax,ax
- ret
-
- LocalDisableA20 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* IsA20On - FUNCTION 07h *
- ;* *
- ;* Returns the state of the A20 line *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise *
- ;* REGS: AX, CX, DI, SI and Flags clobbered *
- ;* *
- ;* INTERNALLY REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- LowMemory label dword ; Set equal to 0000:0080
- dw 00080h
- dw 00000h
-
- HighMemory label dword
- dw 00090h ; Set equal to FFFF:0090
- dw 0FFFFh
-
- IsA20On proc near
-
- push ds
- push es
-
- lds si,cs:LowMemory ; Compare the four words at 0000:0080
- les di,cs:HighMemory ; with the four at FFFF:0090
- mov cx,4
- cld
- repe cmpsw
-
- pop es
- pop ds
- xor ax,ax
-
- jcxz short IAONoWrap ; Are the two areas the same?
- inc ax ; No, return A20 Enabled
-
- IAONoWrap: xor bl,bl
- ret ; Yes, return A20 Disabled
-
- IsA20On endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* QueryExtMemory - FUNCTION 08h *
- ;* *
- ;* Returns the size of the largest free extended memory block in K *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = Size of largest free block in K. BL = Error code *
- ;* DX = Total amount of free extended memory in K *
- ;* REGS: AX, BX, DX, DI, SI and Flags clobbered *
- ;* *
- ;* INTERNALLY REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- QueryExtMemory proc near
-
- ; Init the error code in DL.
- mov dl,ERR_OUTOMEMORY
-
- ; Scan for the largest block marked FREE.
- xor di,di ; DI = Max. size found so far
- xor si,si ; SI = Total amount of free memory
- mov bx,KiddValley
- mov cx,[cHandles] ; Loop through the handle table
- QEMLoop: cmp [bx.Flags],FREEFLAG
- jne short QEMBottom
-
- ; Add this free block to the total.
- add si,[bx.Len] ; CHANGED 7/19/88
-
- ; Is this block larger?
- mov ax,[bx.Len]
- cmp di,ax
- jae short QEMBottom ; CHANGED 7/19/88
-
- ; Yes, save it away.
- mov di,ax
- xor dl,dl ; We ain't Out o' Memory
-
- QEMBottom: add bx,SIZE Handle
- loop QEMLoop
-
- ; Setup the return.
- mov ax,di
- mov bl,dl ; Retrieve the error code
- mov dx,si ; CHANGED 7/19/88
- ret
-
- QueryExtMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* AllocExtMemory - FUNCTION 09h *
- ;* *
- ;* Reserve a block of extended memory *
- ;* *
- ;* ARGS: DX = Amount of K being requested *
- ;* RETS: AX = 1 of successful, 0 otherwise. BL = Error Code *
- ;* DX = 16-bit handle to the allocated block *
- ;* REGS: AX, BX, DX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ; Algorithm -
- ;
- ; Scan the Handle Table looking for BOTH an unused handle and
- ; a free block which is large enough:
- ;
- ; 1. If both are found -
- ; Mark the free block as used and adjust its size.
- ; Make the unused handle a free block containing the remaining
- ; unallocated portion of the original free block.
- ;
- ; 2. If only an unused handle is found -
- ; We're out of memory.
- ;
- ; 3. If only a properly sized free block is found -
- ; We only have one handle left.
- ; Mark the free block as used. The requester gets all of the
- ; block's memory.
- ;
- ; 4. If neither are found -
- ; We're out of memory.
-
- hFreeBlock dw ?
- hUnusedBlock dw ?
-
- AllocExtMemory proc near
-
- cli ; This is a non-reentrant function
-
- ; Scan the handle table looking for BOTH an unused handle and
- ; a free block which is large enough.
- xor ax,ax
- mov [hFreeBlock],ax
- mov [hUnusedBlock],ax
- mov bx,KiddValley
- mov cx,[cHandles] ; Loop through the handle table
-
- ; Have we already found a free block which is large enough?
- AEMhLoop: cmp [hFreeBlock],0
- jne short AEMUnused ; Yes, see if this one is unused
-
- ; Is this block free?
- cmp [bx.Flags],FREEFLAG
- jne short AEMUnused ; No, see if it is unused
-
- ; Is it large enough?
- cmp dx,[bx.Len]
- ja short AEMNexth ; No, get the next handle
-
- ; Save this guy away.
- mov [hFreeBlock],bx
- jmp short AEMBottom
-
- AEMUnused: ; Have we already found an unused handle?
- cmp [hUnusedBlock],0
- jne short AEMNexth ; Yes, get the next handle
-
- ; Is this block unused?
- cmp [bx.Flags],UNUSEDFLAG
- jne short AEMNexth ; No, get the next handle
-
- ; Save this guy away.
- mov [hUnusedBlock],bx
-
- ; Have we found what we are looking for?
- cmp [hFreeBlock],0
- je short AEMNexth
- AEMBottom: cmp [hUnusedBlock],0
- jne short AEMGotBoth ; Yes, continue
-
- AEMNexth: ; Get the next handle
- add bx,SIZE Handle
- loop AEMhLoop
-
- ; We are at the end of the handle table and we didn't find both
- ; things we were looking for. Did we find a free block?
- mov si,[hFreeBlock]
- or si,si
- jnz short AEMRetSuc ; Yes, Case 3 - Alloc the entire block
-
- ; Did we find an unused handle?
- cmp [hUnusedBlock],0
- je short AEMOOHandles ; No, Case 4 - We're out of handles
-
- ; Case 2 - Is this a request for a zero-length handle?
- or dx,dx
- jnz short AEMOOMemory ; No, we're out of memory
-
- ; Reserve the zero-length handle.
- mov si,[hUnusedBlock]
- mov [hFreeBlock],si
- jmp short AEMRetSuc
-
- AEMGotBoth: ; We're at Case 1 above.
- ; Mark the free block as used (done below) and adjust its size.
- ; Make the unused handle a free block containing the remaining
- ; unallocated portion of the original free block.
- mov si,[hFreeBlock]
- mov di,[hUnusedBlock]
-
- ; Unused.Base = Old.Base + request
- mov ax,[si].Base
- add ax,dx
- mov [di].Base,ax
-
- ; New.Len = request
- mov ax,dx
- xchg [si].Len,ax
-
- ; Unused.Len = Old.Len - request
- sub ax,dx
- mov [di].Len,ax
- mov [di].Flags,FREEFLAG ; Unused.Flags = FREE
-
- AEMRetSuc: ; Complete the allocation.
- mov [si].Flags,USEDFLAG ; New.Flags = USED
- mov dx,[hFreeBlock]
- mov ax,1
- xor bl,bl
- ret
-
- AEMOOMemory:mov bl,ERR_OUTOMEMORY
- jmp short AEMErrRet
-
- AEMOOHandles:
- mov bl,ERR_OUTOHANDLES
- AEMErrRet: xor ax,ax ; Return failure
- mov dx,ax
- ret
-
- AllocExtMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* ValidateHandle - *
- ;* *
- ;* Validates an extended memory block handle *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: Carry is set if the handle is valid *
- ;* REGS: Preserved except the carry flag *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ValidateHandle proc near
-
- pusha ; Save everything
- mov bx,dx ; Move the handle into BX
-
- ; The handle must be equal to or above "KiddValley".
- cmp bx,[KiddValley]
- jb short VHOne
-
- ; The handle must not be above "KiddValleyTop".
- cmp bx,[KiddValleyTop]
- ja short VHOne
-
- ; (The handle-"KiddValley") must be a multiple of a handle's size.
- sub dx,[KiddValley]
- mov ax,dx
- xor dx,dx
- mov cx,SIZE Handle
- div cx
- or dx,dx ; Any remainder?
- jnz short VHOne ; Yup, it's bad
-
- ; Does the handle point to a currently USED block?
- cmp [bx.Flags],USEDFLAG
- jne short VHOne ; This handle is not being used.
-
- ; The handle looks good to me...
- popa ; Restore everything
- stc ; Return success
- ret
-
- VHOne: ; It's really bad.
- popa ; Restore everything
- clc ; Return failure
- ret
-
- ValidateHandle endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* FreeExtMemory - FUNCTION 0Ah *
- ;* *
- ;* Frees a block of extended memory which was allocated via AllocExt *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
- ;* REGS: AX, BX, CX, DX, SI, DI and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- FreeExtMemory proc near
-
- cli ; This is a non-reentrant function
-
- ; Make sure that the handle is valid.
- call ValidateHandle
- jnc short FEMBadh
- mov si,dx ; Move the handle into SI
-
- ; Make sure that the handle points to a FREE block.
- cmp [si].cLock,0
- jne short FEMLockedh
-
- ; Mark the block as FREE and cancel any locks.
- mov [si].Flags,FREEFLAG
- mov [si].cLock,0
-
- ; Is an adjacent block also free?
- FEMScanIt: mov bx,[si].Base ; BX = Bottom of block
- mov ax,bx
- add ax,[si].Len ; AX = Top of block
-
- ; Search for an adjacent FREE block.
- mov di,[KiddValley] ; DI = Handle being scanned
-
- mov cx,cHandles ; Loop through the handle table
- FEMLoopTop: cmp [di].Flags,FREEFLAG ; Is this block free?
- jne short FEMNexth ; No, continue
-
- ; Is this block just above the one we are freeing?
- mov dx,[di].Base
- cmp dx,ax
- je short FEMBlockAbove ; Yes, coaless upwards
-
- ; Is it just below?
- add dx,[di].Len
- cmp dx,bx
- je short FEMBlockBelow ; Yes, coaless downwards
-
- FEMNexth: add di,SIZE Handle
- loop FEMLoopTop
-
- ; No adjacent blocks to coaless.
- mov ax,1 ; Return success
- xor bl,bl
- ret
-
- ; Exchange the pointer to the "upper" and "lower" blocks.
- FEMBlockBelow:
- xchg si,di
-
- ; Move the free block above into the current handle.
- FEMBlockAbove:
- mov dx,[si].Len
- add dx,[di].Len ; Combine the lengths
- mov [si].Len,dx
- mov [di].Flags,UNUSEDFLAG ; Mark old block's handle as UNUSED
- jmp short FEMScanIt ; Rescan the list
-
- FEMBadh: mov bl,ERR_INVALIDHANDLE
- jmp short FEMErrExit
-
- FEMLockedh: mov bl,ERR_EMBLOCKED
- FEMErrExit: xor ax,ax ; Return failure
- ret
-
- FreeExtMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* LockExtMemory - FUNCTION 0Ch *
- ;* *
- ;* Locks a block of extended memory *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: AX = 1 of successful, 0 otherwise. BL = Error code *
- ;* DX:BX = 32-bit linear address of the base of the memory block *
- ;* REGS: AX, BX, DX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- LockExtMemory proc near
-
- cli ; This is a non-reentrant function
-
- ; Is the handle valid?
- call ValidateHandle
- jnc short LEMBadh
- mov bx,dx ; Move the handle into BX
-
- ; Are we at some preposterously large limit?
- cmp [bx.cLock],0FFh
- je short LEMOverflow
-
- ; Lock the block.
- inc [bx.cLock]
-
- ; Return the 32-bit address of its base.
- mov dx,[bx.Base]
- mov bx,dx
- shr dx,6
- shl bx,10
-
- ; Return success.
- mov ax,1
- ret
-
- LEMBadh: mov bl,ERR_INVALIDHANDLE
- jmp short LEMErrExit
-
- LEMOverflow:mov bl,ERR_LOCKOVERFLOW
- LEMErrExit: xor ax,ax ; Return failure
- mov dx,ax
- ret
-
- LockExtMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* UnlockExtMemory - FUNCTION 0Dh *
- ;* *
- ;* Unlocks a block of extended memory *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
- ;* REGS: AX, BX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- UnlockExtMemory proc near
-
- cli ; This is a non-reentrant function
-
- ; Is the handle valid?
- call ValidateHandle
- jnc short UEMBadh
- mov bx,dx ; Move the handle into BX
-
- ; Does the handle point to a locked block?
- cmp [bx.cLock],0
- je short UEMUnlocked ; No, return error
-
- ; Unlock the block.
- dec [bx.cLock]
-
- mov ax,1 ; Return success
- xor bl,bl
- ret
-
- UEMUnlocked:mov bl,ERR_EMBUNLOCKED
- jmp short UEMErrExit
-
- UEMBadh: mov bl,ERR_INVALIDHANDLE
- UEMErrExit: xor ax,ax
- ret
-
- UnlockExtMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GetExtMemoryInfo - FUNCTION 0Eh *
- ;* *
- ;* Gets other information about an extended memory block *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
- ;* BH = EMB's lock count *
- ;* BL = Total number of unused handles in the system *
- ;* DX = EMB's length *
- ;* REGS: AX, BX, CX, DX and Flags clobbered *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- GetExtMemoryInfo proc near
-
- cli ; This is a non-reentrant function
-
- ; Is the handle valid?
- call ValidateHandle
- jnc short GEMBadh
- mov si,dx ; Move the handle into SI
-
- ; Count the number of handles which are not currently being used.
- xor al,al
- mov bx,[KiddValley]
- mov cx,[cHandles] ; Loop through the handle table
- GEMLoop: cmp [bx.Flags],USEDFLAG ; Is this handle in use?
- je short GEMNexth ; Yes, continue
- inc al ; No, increment the count
- GEMNexth: add bx,SIZE Handle
- loop GEMLoop
-
- ; Setup the return.
- mov dx,[si.Len] ; Length in DX
- mov bh,[si.cLock] ; Lock count in BH
- mov bl,al
- mov ax,1
- ret
-
- GEMBadh: mov bl,ERR_INVALIDHANDLE
- xor ax,ax
- ret
-
- GetExtMemoryInfo endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* ReallocExtMemory - FUNCTION 0Fh *
- ;* *
- ;* Reallocates a block of extended memory *
- ;* *
- ;* ARGS: DX = 16-bit handle to the extended memory block *
- ;* RETS: AX = 1 if successful, 0 otherwise. BL = Error code *
- ;* REGS: *
- ;* *
- ;* INTERNALLY NON-REENTRANT *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ; FUNCTION NOT YET IMPLEMENTED
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* NOTE: RequestUMB and ReleaseUMB will not be implemented by HIMEM. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* MoveExtMemory - FUNCTION 0Bh *
- ;* *
- ;* Copys a block of memory from anywhere to anywhere *
- ;* *
- ;* ARGS: ES:SI = Pointer to an Extended Memory Block Move Structure *
- ;* (NOTE: Originally passed in as DS:SI) *
- ;* RETS: AX = 1 of successful, 0 otherwise. BL = Error code. *
- ;* REGS: Everybody clobbered *
- ;* *
- ;* INTERNALLY REENTRANT (believe it or not) *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- EVEN ; Must be word aligned.
-
- MoveBlock:
-
- MEM3_Data label byte ; Start of MoveBlock data
- MoveBlock286:
-
- include xm286.asm
-
-
- ;*--------------------------------------------------------------------------*
-
- MoveBlock386:
-
- include xm386.asm
-
- EndMoveBlock386:
-
-
- ;****************************************************************************
- ;* *
- ;* A20 Handler Section: *
- ;* *
- ;* The Init code copies the proper A20 Handler in place just below the *
- ;* proper MoveBlock routine. *
- ;* *
- ;* NOTE: A20 HANDLERS MUST ONLY HAVE RELATIVE JUMPS! HOWEVER ANY CALLS TO *
- ;* FUNCTIONS OUTSIDE OF THE HANDLER MUST BE NON-RELATIVE! The best *
- ;* method is to call thru a variable such as ControlJumpTable[n]. *
- ;* *
- ;****************************************************************************
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* AT_A20Handler - HARDWARE DEP. *
- ;* *
- ;* Enable/Disable the A20 line on non-PS/2 machines *
- ;* *
- ;* ARGS: AX = 0 for Disable, 1 for Enable *
- ;* RETS: AX = 1 for success, 0 otherwise *
- ;* REGS: AX, CX and Flags clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- AT_A20Handler proc near
-
- or ax,ax
- jz short AAHDisable
-
- AAHEnable: call Sync8042 ; Make sure the Keyboard Controller is Ready
- jnz short AAHErr
-
- mov al,0D1h ; Send D1h
- out 64h,al
- call Sync8042
- jnz short AAHErr
-
- mov al,0DFh ; Send DFh
- out 60h,al
- call Sync8042
- jnz short AAHErr
-
- ; Wait for the A20 line to settle down (up to 20usecs)
- mov al,0FFh ; Send FFh (Pulse Output Port NULL)
- out 64h,al
- call Sync8042
- jnz short AAHErr
- jmp short AAHExit
-
- AAHDisable: call Sync8042 ; Make sure the Keyboard Controller is Ready
- jnz short AAHErr
-
- mov al,0D1h ; Send D1h
- out 64h,al
- call Sync8042
- jnz short AAHErr
-
- mov al,0DDh ; Send DDh
- out 60h,al
- call Sync8042
- jnz short AAHErr
-
- ; Wait for the A20 line to settle down (up to 20usecs)
- mov al,0FFh ; Send FFh (Pulse Output Port NULL)
- out 64h,al
- call Sync8042
-
- AAHExit: mov ax,1
- ret
-
- AAHErr: xor ax,ax
- ret
-
- AT_A20Handler endp
-
-
- ;*--------------------------------------------------------------------------*
-
- Sync8042 proc near
-
- xor cx,cx
- S8InSync: in al,64h
- and al,2
- loopnz S8InSync
- ret
-
- Sync8042 endp
-
- EndAT_A20Handler:
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* PS2_A20Handler - HARDWARE DEP. *
- ;* *
- ;* Enable/Disable the A20 line on PS/2 machines *
- ;* *
- ;* ARGS: AX = 0 for Disable, 1 for Enable *
- ;* RETS: AX = 1 for success, 0 otherwise *
- ;* REGS: AX, CX and Flags clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- PS2_PORTA equ 0092h
- PS2_A20BIT equ 00000010b
-
- PS2_A20Handler proc near
-
- or ax,ax
- jz short PAHDisable
-
- PAHEnable: in al,PS2_PORTA ; Get the current A20 state
- test al,PS2_A20BIT ; Is A20 already on?
- jnz short PAHErr
-
- or al,PS2_A20BIT ; Turn on the A20 line
- out PS2_PORTA,al
-
- xor cx,cx ; Make sure we loop for awhile
- PAHIsItOn: in al,PS2_PORTA ; Loop until the A20 line comes on
- test al,PS2_A20BIT
- loopz PAHIsItOn
- jz short PAHErr ; Unable to turn on the A20 line
- jmp short PAHExit
-
- PAHDisable: in al,PS2_PORTA ; Get the current A20 state
- and al,NOT PS2_A20BIT ; Turn off the A20 line
- out PS2_PORTA,al
-
- xor cx,cx ; Make sure we loop for awhile
- PAHIsItOff: in al,PS2_PORTA ; Loop until the A20 line goes off
- test al,PS2_A20BIT
- loopnz PAHIsItOff
- jnz short PAHErr ; Unable to turn off the A20 line
-
- PAHExit: mov ax,1
- ret
-
- PAHErr: xor ax,ax
- ret
-
- PS2_A20Handler endp
-
- EndPS2_A20Handler:
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* $6300Plus_A20Handler - HARDWARE DEP. *
- ;* *
- ;* Enable/Disable address lines A20-A23 on AT&T 6300 Plus *
- ;* *
- ;* ARGS: AX = 0 for Disable, 1 for Enable *
- ;* RETS: AX = 1 for success, 0 otherwise *
- ;* REGS: AX, BX, and Flags clobbered *
- ;* *
- ;* Note: Don't want to do two back to back disables on PLUS, *
- ;* so we call IsA20On to see if it is necessary. *
- ;* Warning: The calcuation of the ReturnBack label depends on the *
- ;* expectation that this routine is being moved at init time. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- PLUS_PORT equ 03F20h
- PLUS_STATUS equ 03FA0h
- PLUS_SET equ 10000000b ; Turn on A20-A23
- PLUS_RESET equ 00010000b ; Turn off A20-A23 and point to our routine
-
- $6300PLUS_A20Handler proc near
- mov bx,ax
- push dx
- mov dx,PLUS_STATUS
- in al,dx
- pop dx
- and ax,1
- cmp ax,bx
- jne short $6AHEnable
- mov ax,1
- ret ; No, just return
-
- $6AHEnable:
- pushf
- sti
- mov al,PLUS_SET
- or bx,bx ; Zero if disable
- jnz short $6AHNext
- mov al,PLUS_RESET
-
- $6AHNext: push dx ; Set/reset the port
- mov dx,PLUS_PORT
- out dx,al
- pop dx
- or bx,bx
- jnz short $6AHNext1
- call $6300Reset ; Reset the processor
- $6AHNext1:
- popff
- mov ax,1
- ret
-
- $6300Plus_A20Handler endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* $6300Reset - HARDWARE DEP. *
- ;* *
- ;* Reset the 80286 in order to turn off the address lines on the 6300 PLUS. *
- ;* This is the only way to do this on the current hardware. *
- ;* The processor itself is reset by reading or writing port 03F00h. *
- ;* *
- ;* Uses flags. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- $6300Reset proc near
-
- pusha ; Save world
- push ds ; Save segments
- push es
- mov ax,BiosSeg ; Point to the BIOS segment
- mov ds,ax ; ds -> 40h
-
- ; Setup the reset return address.
- assume ds:nothing
- push word ptr ds:[RealLoc1] ; Save what might have been here
- push word ptr ds:[RealLoc1+2]
-
- ; Load our return address, remembering that we will be relocated
- ; at init time.
- mov word ptr ds:[RealLoc1+2],cs
- mov ax,cs:[A20Handler]
- add ax,offset ReturnBack-offset $6300Plus_A20Handler
- mov word ptr ds:[RealLoc1],ax
- mov cs:[OldStackSeg],ss ; Save the stack segment, too
-
- ; Reset the processor - turning off A20 in the process.
- mov dx,03F00h
- in ax,dx
-
- ; We shouldn't get here. Halt the machine if we do.
- nop
- nop
- nop
- nop
- cli
- hlt
-
- ReturnBack: mov ss,cs:[OldStackSeg] ; Start the recovery
- pop word ptr ds:[RealLoc1+2] ; ROM code has set ds->40h
- pop word ptr ds:[RealLoc1]
- pop es
- pop ds
-
- assume ds:code
- xor al,al
- mov dx,PLUS_PORT
- out dx,al
- popa
- ret
-
- $6300Reset endp
-
- End6300Plus_Handler:
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* HP_A20Handler - HARDWARE DEP. *
- ;* *
- ;* Enable/Disable the A20 line on HP Vectra machines *
- ;* *
- ;* ARGS: AX = 0 for Disable, 1 for Enable *
- ;* RETS: AX = 1 for success, 0 otherwise *
- ;* REGS: AX, CX and Flags clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- HP_A20Handler proc near
-
- or ax,ax
- jz short HAHDisable
-
- HAHEnable: call HPSync8042 ; Make sure the Keyboard Controller is ready
- jnz short HAHErr
-
- mov al,0DFh ; Send DFh
- out 64h,al
- call HPSync8042
- jnz short HAHErr
-
- mov al,0DFh ; Send second DFh
- out 64h,al
- call HPSync8042
- jnz short HAHErr
- jmp short HAHExit
-
- HAHDisable: call HPSync8042 ; Make sure the Keyboard Controller is Ready
- jnz short HAHErr
-
- mov al,0DDh ; Send DDh
- out 64h,al
- call HPSync8042
- jnz short HAHErr
-
- mov al,0DDh ; Send second DDh
- out 64h,al
- call HPSync8042
- jnz short HAHErr
-
- HAHExit: mov ax,1
- ret
-
- HAHErr: xor ax,ax
- ret
-
- HP_A20Handler endp
-
-
- ;*--------------------------------------------------------------------------*
-
- HPSync8042 proc near
-
- xor cx,cx
- H8InSync: in al,64h
- and al,2
- loopnz H8InSync
- ret
-
- HPSync8042 endp
-
- EndHP_A20Handler:
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Extended Memory Handle Table - *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ; Actually, the handle table will be located just after the end of whichever
- ; A20 Handler is installed and will overwrite the others. In large cases
- ; however, it could extend beyond all of these guys and crunch the Init code.
- ; Hence this buffer. If the driver ever gets over 64K (heaven forbid) this
- ; scheme should be reworked.
-
- ; Guarantee space for all handles. Kinda overkill but any extra will be
- ; discarded with the Init code.
-
- HandleFiller dw MAXHANDLES * SIZE Handle DUP(?)
-
-
- ;****************************************************************************
- ;* *
- ;* NOTE: Code below here will be discarded after driver initialization. *
- ;* *
- ;****************************************************************************
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* InitDriver - *
- ;* *
- ;* Called when driver is Initialized. *
- ;* *
- ;* ARGS: ES:DI = Address of the Request Header *
- ;* RETS: AX = 0, pHdr.Address = Bottom of resident driver code *
- ;* REGS: AX, CX and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- InitLine dw MoveBlock ; The line which defines what will be dis-
- ; carded after the driver is initialized
- InitDriver proc near
-
- ; Display the sign on message.
- mov ah,9h
- mov dx,offset SignOnMsg
- int 21h
-
- ; Is this DOS 3.00 or higher?
- mov ah,30h
- int 21h ; Get DOS versions number
- cmp al,3
- jae short IDCheckXMS
-
- mov dx,offset BadDOSMsg
- jmp short IDFlushMe2
-
- ; Is another XMS driver already installed?
- IDCheckXMS: mov ax,4300h
- int 2Fh
- cmp al,80h ; Is INT 2F hooked?
- jne short IDNotInYet
- mov dx,offset NowInMsg
- jmp short IDFlushMe2
-
- ; What kind of processor are we on?
- IDNotInYet: call MachineCheck
- cmp ax,1 ; Is it an 8086/8088?
- jne short IDProcOK
- mov dx,offset On8086Msg
- jmp short IDFlushMe
-
- ; Is there any Compaq BIM?
- IDProcOK:
- call GetBIMMemory
- or ax,ax
- jz short IDNoBIM
-
- ; How much extended memory is installed?
- call GetInt15Memory
- cmp ax,64 ; Is there >= 64K of extended?
- jb short IDNoHMA ; Nope - No HMA
- jmp short IDHMAOK ; Yup - continue
-
- ; How much extended memory is installed?
- IDNoBIM: call GetInt15Memory
- cmp ax,64 ; Is there >= 64K of extended?
- jae short IDHMAOK ; Yup - continue
-
- or ax,ax ; Is there any extended?
- jnz short IDNoHMA ; Yup - No HMA
-
- ; We can't find any memory to manage.
- mov dx,offset NoExtMemMsg
- IDFlushMe2: jmp short IDFlushMe
-
- ; There isn't enough for the HMA, but there is some extended
- ; memory which we can manage.
- IDNoHMA: mov dx,offset NoHMAMsg
- mov ah,9h
- int 21h
- jmp short IDFinalInit
-
- IDHMAOK: mov [fHMAMayExist],1
-
- ; Install the proper MoveBlock function.
- IDFinalInit:call InstallMoveBlock
-
- ; Install the proper A20 handler.
- call InstallA20
-
- ; Was A20 on already?
- call IsA20On
- xor ax,1
- mov [fCanChangeA20],al ; Yes, don't ever disable it
- cmp al,0
- jne short IDDiddler
-
- ; Display the "A20 Already On" message.
- mov dx,offset A20OnMsg
- mov ah,9h ; CHANGED - 8/9/88
- int 21h
-
- ; Can we successfully diddle A20? CHANGED - 8/9/88
- IDDiddler: call LocalEnableA20 ; Try to enable A20
- or ax,ax ; Did we do it?
- jz short IDBadA20 ; Nope - phoosh ourselves
-
- call IsA20On ; Is A20 on?
- or ax,ax
- jz short IDBadA20 ; Nope - phoosh ourselves
-
- call LocalDisableA20 ; Try to disable A20
- or ax,ax ; Did we do it?
- jnz short IDA20Cont ; Yup - continue
-
- cmp [fCanChangeA20],1 ; Has A20 been permenantly enabled?
- je short IDGetParms ; Yup - continue
- jmp short IDBadA20 ; Nope - phoosh ourselves
-
- IDA20Cont: call IsA20On ; Is A20 off?
- or ax,ax
- jz short IDGetParms ; Yup - continue
-
- ; A20 ain't doing it.
- IDBadA20: mov dx,offset BadA20Msg
-
- ; Display the message in DX followed by the "Flush" message.
- IDFlushMe: mov ah,9h
- int 21h
- mov dx,offset FlushMsg
- mov ah,9h
- int 21h
-
- ; Discard the entire driver.
- xor ax,ax
- mov [InitLine],ax
- les di,[pReqHdr]
- mov es:[di.Units],al
- jmp short IDReturn
-
- ; Process the command line parameters.
- IDGetParms: call GetParms
-
- ; Initialize the Handle Table.
- call InitHandles
-
- ; Display the success messages.
- cmp [fHMAMayExist],0
- je short IDIgnition
- mov dx,offset HMAOKMsg
- mov ah,9h
- int 21h
-
- ; "Turn On" the driver.
- IDIgnition: call HookInt2F
-
- ; Discard the initialization code.
- IDReturn: les di,[pReqHdr]
- mov ax,[InitLine]
- mov word ptr es:[di.Address][0],ax
- mov word ptr es:[di.Address][2],cs
-
- ; Return success.
- xor ax,ax
- ret
-
- InitDriver endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* HookInt2F - *
- ;* *
- ;* Insert the INT 2F hook *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, SI, ES and Flags are clobbered *
- ;* *
- ;* EXTERNALLY NON-REENTRANT *
- ;* Interrupts must be disabled before calling this function. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- HookInt2F proc near
-
- ; Save the current INT 2F vector
- cli
- xor ax,ax
- mov es,ax
- mov si,2Fh * 4 ; ES:SI = Address of 2F vector
-
- ; Exchange the old vector with the new one
- mov ax,offset Int2FHandler
- xchg ax,es:[si][0]
- mov word ptr [PrevInt2F][0],ax
- mov ax,cs
- xchg ax,es:[si][2]
- mov word ptr [PrevInt2F][2],ax
- sti
- ret
-
- HookInt2F endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* MachineCheck - *
- ;* *
- ;* Determines the CPU type. *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if we're on an 8086/8088 or an 80186, 0 otherwise *
- ;* REGS: AX and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ; NOTE: This is the "official" Intel method for determining CPU type.
-
- MachineCheck proc near
-
- xor ax,ax ; Move 0 into the Flags register
- push ax
- popf
- pushf ; Try and get it back out
- pop ax
- and ax,0F000h ; If the top four bits are set...
- cmp ax,0F000h
- je short MC_8086 ; ...it's an 8086 machine
-
- mov ax,0F000h ; Move F000h into the Flags register
- push ax
- popf
- pushf ; Try and get it back out
- pop ax
- and ax,0F000h ; If the top four bits aren't set...
- jz short MC_80286 ; ...it's an 80286 machine
-
- ; We're on an 80386 machine
- mov ax,3
- ret
-
- MC_80286: ; We're on an 80286 machine
- mov ax,2
- ret
-
- MC_8086: ; We're on an 8086 machine
- mov ax,1
- ret
-
- MachineCheck endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GetBIMMemory - *
- ;* *
- ;* Look for Compaq 'Built In Memory' and add it to the pool of *
- ;* available memory *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = Amount of BIM memory found *
- ;* REGS: AX, BX, CX, and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- ; "Built In Memory" (BIM) starts at FE00:0000h and grows downward. It is
- ; controlled by a data structure at F000:FFE0h. Changing the data structure
- ; involves un-write-protecting the ROMs (!) by flipping bit 1 of 80C00000.
-
- pBIMSTRUCT equ 0FFE0h
- AVAILABLE equ 0 ; Set to -1 if BIM isn't around
- TOTALBIM equ 2 ; Total amount of BIM in the system
- AVAILBIM equ 4 ; Amount of BIM available in paragraphs
- LASTUSED equ 6 ; Paragraph address of last (lowest) used
- ; paragraph of BIM
-
- pCOMPAQ label dword
- dw 0FFE8h
- dw 0F000h
-
- szCOMPAQ db '03COMPAQ'
-
- pRAMRELOC label dword
- dw 00000h
- dw 080C0h
-
- GDT_TYPE struc
- dw 0,0,0,0
- dw 0,0,0,0
-
- S_LIMIT dw 1
- S_BASE_LOW dw 0
- S_BASE_HI db 0
- S_RIGHTS db 93h
- S_RESERVED dw 0
-
- D_LIMIT dw 1
- D_BASE_LOW dw 0000h
- D_BASE_HI db 0C0h
- D_RIGHTS db 93h
- D_RES386 db 0
- D_BASE_XHI db 080h
-
- dw 0,0,0,0
- dw 0,0,0,0
- GDT_TYPE ends
-
- BIMGDT GDT_TYPE <>
-
- BIMBuffer dw ?
-
-
- GetBIMMemory proc near
-
- xor ax,ax
-
- ; Are we on a Compaq 386 machine?
- push es
-
- ; Set up the comparison.
- les di,cs:pCOMPAQ
- mov si,offset szCOMPAQ
- mov cx,8
- cld
- rep cmpsb ; Do the comparison
-
- jne short FCMNoMem2 ; Nope, return
-
- ; Is there a 32-bit memory board installed?
- mov bx,pBIMSTRUCT
- mov bx,es:[bx] ; De-reference the pointer
- mov dx,es:[bx+AVAILABLE] ; -1 means no board is installed
- inc dx
- jz short FCMNoMem2 ; Nope, return
-
- ; How much memory is available and where does it start?
- mov dx,es:[bx+AVAILBIM] ; Size in paragraphs
- or dx,dx ; Any left?
- jz short FCMNoMem
- mov cx,dx ; CX = Size in paragraphs
- mov ax,es:[bx+LASTUSED]
- sub ax,cx ; AX = Starting location - F0000h
- ; in paragraphs
- push es ; Save for a rainy day...
- push bx
- push ax
-
- ; Change AX to the starting location in K.
- shr ax,4
- add ax,0F000h
- shr ax,2
-
- ; Change CX to the size in K.
- shr cx,6
-
- ; Store away for use by HookInt15().
- mov [BIMBase],ax
- mov [BIMLength],cx
-
- ; Un-WriteProtect the ROMs.
- mov si,offset BIMGDT ; Set up the BlockMove GDT
- mov ax,cs
- mov es,ax
- mov cx,16
- mul cx
- add ax,offset BIMBuffer
- adc dl,0
- mov [si.S_BASE_LOW],ax
- mov [si.S_BASE_HI],dl
- mov cx,1
-
- mov word ptr [BIMBuffer],0FEFEh ; FEh unlocks the ROMs
-
- mov ah,87h ; Do the BlockMove
- int 15h
- or ah,ah ; Was there an error?
- jz short FCMReserve ; Nope - continue
-
- ; Return error.
- pop ax ; Clean up
- pop bx
- pop es
- xor ax,ax
- mov [BIMBase],ax
- mov [BIMLength],ax
- FCMNoMem2: jmp short FCMNoMem
-
- ; Change the ROM values to reserve the BIM stuff.
- FCMReserve: pop ax
- pop bx
- pop es
- mov word ptr es:[bx+AVAILBIM],0 ; Reserve all remaining BIM
- mov word ptr es:[bx+LASTUSED],ax
-
- ; Re-WriteProtect the ROMs.
- push cs
- pop es
- mov si,offset BIMGDT ; Set up the BlockMove GDT
-
- mov word ptr [BIMBuffer],0FCFCh ; FCh unlocks the ROMs
-
- mov ah,87h ; Do the BlockMove
- int 15h
-
- mov ax,1 ; Return success
-
- FCMNoMem: pop es
- ret
-
- GetBIMMemory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GetInt15Memory - *
- ;* *
- ;* Returns the amount of memory INT 15h, Function 88h says is free *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = Amount of free extended memory in K-bytes *
- ;* REGS: AX and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- GetInt15Memory proc near
-
- ; Check for 6300 Plus (to set "MemCorr").
- call Is6300Plus
-
- ; Get the amount of extended memory Int 15h says is around.
- mov ah,88h
- clc
- int 15h ; Is Function 88h around?
- jnc short GIM100
- xor ax,ax ; No, return 0
- ret
-
- GIM100: sub ax,[MemCorr] ; Compensate for 6300 Plus machines
- ret
-
- GetInt15Memory endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* InstallMoveBlock - HARDWARE DEP. *
- ;* *
- ;* Attempt to install the proper MoveBlock function. *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, CX, DI, SI, ES and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- InstallMoveBlock proc near
-
- ; Are we on a 386 machine?
- call MachineCheck
- cmp ax,3
- je short IMBOn386 ; Yes, install the 386 routine
-
- ; Install the 286 MoveBlock routine.
- mov [InitLine],offset EndMoveBlock286
- call InitMoveExtended286
- ret
-
- ; Install the 386 MoveBlock routine.
- IMBOn386: mov si,offset MoveBlock386
- mov cx,(offset EndMoveBlock386 - offset MoveBlock386)
-
- ; REP MOV the routine into position.
- cld
- push cs
- pop es
- mov di,offset MoveBlock
- add [InitLine],cx
- rep movsb
- call InitMoveBlock386
- ret
-
- InstallMoveBlock endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* InitMoveBlock386 - HARDWARE DEP. *
- ;* *
- ;* Initializes the 386 MoveBlock routine *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, CX, DX and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- InitMoveBlock386 proc near
-
- mov ax,cs ; dx has CS of codeg
- mov [patch3],ax ; Patch code
- mov cx,16
- mul cx
- mov [descCS].LO_apDesc386,ax ; Set up selector for our CS
- mov [descCS].MID_apDesc386,dl
- add ax,offset code:OurGDT ; Calculate Base of GDT
- adc dx,0
- mov [GDTPtr.LO_apBaseGdt],ax
- mov [GDTPtr.HI_apBaseGdt],dx
- mov ax,offset code:MoveExtended386+MEM3_Offset
- mov ControlJumpTable[0Bh*2],ax
- ret
-
- InitMoveBlock386 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* InstallA20 - HARDWARE DEP. *
- ;* *
- ;* Attempt to install the proper A20 Handler *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, CX, DI, SI, ES and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- InstallA20 proc near
-
- ; Are we on a 6300 Plus?
- call Is6300Plus
- or ax,ax
- jz short IAChkPS2
-
- ; Yes, relocate 6300 Plus A20 handler.
- mov si,offset $6300PLUS_A20Handler
- mov cx,(offset End6300PLUS_Handler - offset $6300PLUS_A20Handler)
- jmp short IAMoveIt
-
- ; Are we on a PS/2?
- IAChkPS2: call IsPS2Machine
- cmp ax,1
- jne short IACheckHP
-
- ; Yes, relocate the PS/2 A20 handler.
- mov si,offset PS2_A20Handler
- mov cx,(offset EndPS2_A20Handler - offset PS2_A20Handler)
- jmp short IAMoveIt
-
- ; Are we on a HP Vectra?
- IACheckHP: call IsHPMachine
- cmp ax,1
- jne short IAOnAT
-
- ; Yes, relocate the HP A20 handler.
- mov si,offset HP_A20Handler
- mov cx,(offset EndHP_A20Handler - offset HP_A20Handler)
- jmp short IAMoveIt
-
- IAOnAT: mov si,offset AT_A20Handler
- mov cx,(offset EndAT_A20Handler - offset AT_A20Handler)
-
- ; REP MOV the proper handler into position.
- IAMoveIt: cld
- push cs
- pop es
- mov di,[InitLine]
- mov [A20Handler],di
- add [InitLine],cx
- rep movsb
- ret
-
- InstallA20 endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* GetParms - *
- ;* *
- ;* Get any parameters off of the HIMEM command line *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, BX, CX, DX, DI, SI, ES and Flags clobbered *
- ;* *
- ;* Side Effects: cHandles and MinHMASize may be changed *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- GPRegSave dw ?
-
- GetParms proc near
-
- push ds
-
- cld
- les di,[pReqHdr]
- lds si,es:[di.pCmdLine] ; DS:SI points to first char
- ; after "DEVICE="
- ; Scan until we see a frontslash or the end of line.
- GPBadParm:
- GPNextChar: lodsb
- cmp al,'/'
- je short GPGotOne
- cmp al,13
- jne short GPNextChar
- GPDatsAll: pop ds
- ret
-
- ; Save what we found and get the number after it.
- GPGotOne: lodsb
- mov cs:[GPRegSave],ax
-
- ; Scan past the rest of the parm for a number, EOL, or a space.
- GPNeedNum: lodsb
- cmp al,' '
- je short GPBadParm
- cmp al,13
- je short GPBadParm
- cmp al,'0'
- jb short GPNeedNum
- cmp al,'9'
- ja short GPNeedNum
-
- ; Read the number at DS:SI into DX.
- xor dx,dx
- GPNumLoop: sub al,'0'
- cbw
- add dx,ax
- lodsb
- cmp al,' '
- je short GPNumDone
- cmp al,13
- je short GPNumDone
- cmp al,'0'
- jb short GPBadParm
- cmp al,'9'
- ja short GPBadParm
- shl dx,1 ; Stupid multiply DX by 10
- mov bx,dx
- shl dx,1
- shl dx,1
- add dx,bx
- jmp short GPNumLoop
-
- ; Which parameter are we dealing with here?
- GPNumDone: xchg ax,cs:[GPRegSave]
- cmp al,'H' ; HMAMIN= parameter?
- je short GPGotMin
- cmp al,'N' ; NUMHANDLES= parameter?
- jne short GPBadParm
-
- ; Process /NUMHANDLES= parameter.
- GPGotHands: cmp dx,MAXHANDLES
- ja short GPBadParm
-
- or dx,dx ; Zero?
- jz short GPBadParm
-
- mov cs:[cHandles],dx ; Store it
-
- ; Print descriptive message.
- mov dx,offset StartMsg
- call GPPrintIt
- mov ax,cs:[cHandles]
- call GPPrintAX
- mov dx,offset HandlesMsg
- call GPPrintIt
- jmp short GPNextParm
-
- ; Process /HMAMIN= parameter.
- GPGotMin: cmp dx,64
- ja short GPBadParm
-
- push dx
- mov cs:[MinHMASize],dx
-
- ; Print a descriptive message.
- mov dx,offset HMAMINMsg
- call GPPrintIt
- mov ax,cs:[MinHMASize]
- call GPPrintAX
- mov dx,offset KMsg
- call GPPrintIt
-
- pop dx
- mov cl,10 ; Convert from K to bytes
- shl dx,cl
- mov cs:[MinHMASize],dx
-
- ; Were we at the end of the line?
- GPNextParm: mov ax,cs:[GPRegSave]
- cmp al,13
- je short GPExit
- jmp GPNextChar
-
- GPExit: pop ds
- ret
-
- GetParms endp
-
- ;*--------------------------------------------------------------------------*
-
- GPPrintIt proc near
-
- push ds ; Save current DS
- push cs ; Set DS=CS
- pop ds
- mov ah,9h
- int 21h
- pop ds ; Restore DS
- ret
-
- GPPrintIt endp
-
- ;*--------------------------------------------------------------------------*
-
- GPPrintAX proc near
-
- mov cx,10
- xor dx,dx
- div cx
- or ax,ax
- jz short GPAPrint
- push dx
- call GPPrintAX
- pop dx
- GPAPrint: add dl,'0'
- mov ah,2h
- int 21h
- ret
-
- GPPrintAX endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* InitHandles - *
- ;* *
- ;* Initialize the Extended Memory Handle Table *
- ;* *
- ;* ARGS: None *
- ;* RETS: None *
- ;* REGS: AX, BX, CX, and Flags are clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- InitHandles proc near
-
- ; Allocate room for the Handle table at the end.
- mov ax,[InitLine]
- mov [KiddValley],ax
- mov ax,SIZE Handle
- mov cx,[cHandles]
- mul cx
- add [InitLine],ax
-
- ; Init the Handle table.
- mov bx,KiddValley
- xor ax,ax
- mov cx,[cHandles]
- IHTabLoop: mov [bx.Flags],UNUSEDFLAG
- mov [bx.cLock],al
- mov [bx.Base],ax
- mov [bx.Len],ax
- add bx,SIZE Handle
- loop IHTabLoop
-
- ; Store away the top of the table for handle validation.
- mov [KiddValleyTop],bx
- ret
-
- InitHandles endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* Is6300Plus HARDWARE DEP. *
- ;* *
- ;* Check for AT&T 6300 Plus *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if we're on an AT&T 6300 Plus, 0 otherwise *
- ;* REGS: AX, flags used. *
- ;* *
- ;* Side Effects: MemCorr value updated to 384 if necessary. *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- Is6300Plus proc near
-
- xor ax,ax
- push bx
- mov bx,0FC00h ; Look for 'OL' at FC00:50
- mov es,bx
- cmp es:[0050h],'LO'
- jne short I6PNotPlus ; Not found
- mov bx,0F000h
- mov es,bx
- cmp word ptr es:[0FFFDh],0FC00h ; Look for 6300 PLUS
- jne short I6PNotPlus
-
- in al,66h ; Look for upper extended memory
- and al,00001111b
- cmp al,00001011b
- jne short I6PNoMem
- mov [MemCorr],384 ; Save value
-
- I6PNoMem: mov ax,1 ; We found a PLUS
- I6PNotPlus: pop bx
- ret
-
- Is6300Plus endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* IsPS2Machine HARDWARE DEP. *
- ;* *
- ;* Check for PS/2 machine *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if we're on a valid PS/2 machine, 0 otherwise *
- ;* REGS: AX and Flags clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- IsPS2Machine proc near
-
- mov ah,0C0h ; Get System Description Vector
- stc
- int 15h
- jc short IPMNoPS2 ; Error? Not a PS/2.
-
- ; Do we have a "Micro Channel" computer?
- mov al,byte ptr es:[bx+5] ; Get "Feature Information Byte 1"
- test al,00000010b ; Test the "Micro Channel Implemented" bit
- jz short IPMNoPS2
-
- IPMFoundIt: xor ax,ax ; Disable A20. Fixes PS2 Ctl-Alt-Del bug
- call PS2_A20Handler
- mov ax,1
- ret
-
- IPMNoPS2: xor ax,ax
- ret
-
- IsPS2Machine endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* *
- ;* IsHPMachine HARDWARE DEP. *
- ;* *
- ;* Check for HP Vectra Machine *
- ;* *
- ;* ARGS: None *
- ;* RETS: AX = 1 if we're on a HP Vectra machine, 0 otherwise *
- ;* REGS: AX, ES and Flags clobbered *
- ;* *
- ;*--------------------------------------------------------------------------*
-
- IsHPMachine proc near
-
- mov ax,0F000h
- mov es,ax
- mov ax,word ptr es:[0F8h]
- cmp ax,'PH'
- je short IHMFoundIt
- xor ax,ax
- ret
-
- IHMFoundIt: mov ax,1
- ret
-
- IsHPMachine endp
-
-
- ;*--------------------------------------------------------------------------*
- ;* DRIVER MESSAGES *
- ;*--------------------------------------------------------------------------*
-
- SignOnMsg db 13,10,'HIMEM: DOS XMS Driver, Version 2.06 - 3/21/89'
- db 13,10,'Copyright 1988,1989 Microsoft Corp.'
- db 13,10,'$'
-
- BadDOSMsg db 13,10,'ERROR: HIMEM.SYS requires DOS 3.00 or higher.$'
- NowInMsg db 13,10,'ERROR: An Extended Memory Manager is already installed.$'
- On8086Msg db 13,10,'ERROR: HIMEM.SYS requires an 80x86-based machine.$'
- NoExtMemMsg db 13,10,'ERROR: No available extended memory was found.$'
- BadA20Msg db 13,10,'ERROR: Unrecognized A20 hardware.$'
- FlushMsg db 13,10,' XMS Driver not installed.',13,10,13,10,'$'
-
- StartMsg db 13,10,'$'
- HandlesMsg db ' extended memory handles available.$'
- HMAMINMsg db 13,10,'Minimum HMA size set to $'
- KMsg db 'K.$'
-
- NoHMAMsg db 13,10,'WARNING: The High Memory Area is unavailable.',13,10,'$'
- A20OnMsg db 13,10,'WARNING: The A20 Line was already enabled.',13,10,'$'
-
- HMAOKMsg db 13,10,'64K High Memory Area is available.',13,10,13,10,'$'
-
- db 'This program is the property of Microsoft Corporation.'
-
- db 64 dup(0) ; For internationalization
-
- ;*==========================================================================*
-
- code ends
-
- end
-